#include "LoadMap.h"
#include "Resource.h"
#include "Land.h"
#include "Stone.h"
#include "BrickEx.h"
#include "BrickQuestion.h"
#include "Pipe.h"
#include "Cloud.h"
#include "Grass.h"
#include "Mountain.h"
#include "Coin.h"
#include "PowerUp.h"
#include "Pirhana.h"
#include "Star.h"
#include "Goomba.h"
#include "Koopa.h"
#include "CheckPoint.h"

LoadMap::LoadMap(LPDIRECT3DDEVICE9 d3ddv, LPDIRECT3DSURFACE9 backBuffer, LPD3DXSPRITE spriteHandler)
{
	this->d3ddv = d3ddv;
	this->backBuffer = backBuffer;
	this->spriteHandler = spriteHandler;

	numScore = 0;
	numLife = 0;
	numCoin = 0;
	submapToMap = false;
}

std::vector<std::string>& LoadMap::split(const std::string &s, char delim, std::vector<std::string> &elems)
{
	std::stringstream ss(s);
	std::string item;
	while(std::getline(ss, item, delim))
	{
		elems.push_back(item);
	}
	return elems;
}

std::vector<std::string> LoadMap::split(const std::string &s, char delim)
{
	std::vector<std::string> elems;
	return split(s, delim, elems);
}

void LoadMap::loadFileObj(char* file_name)
{
	string data;
	ifstream fileStream(file_name);
	if (fileStream.is_open())
	{
		while (!fileStream.eof())
		{
			data += fileStream.get();
		}
	}
	vector<string> dataSplit = split(data, '\n');
	string row_header = dataSplit[0];
	vector<string> element_row = split(row_header, ' ');
	
	int width, height;
	width = atoi(element_row[0].c_str());		//lay so cot thong tin obj
	height = atoi(element_row[1].c_str());		//so luong obj
	numScore = atoi(element_row[2].c_str());	//so diem, khi load map
	numLife = atoi(element_row[3].c_str());		//so mang, khi load map
	numCoin = atoi(element_row[4].c_str());		//so coin an dc, khi load map

	posX_first = atoi(element_row[5].c_str());		//vi tri ban dau cua mario
	posY_first = atoi(element_row[6].c_str());
	posX_last = atoi(element_row[7].c_str());		//vi tri sau khi load map, tu map phu sang map chinh tro lai, vi tri cua pipe
	posY_last = atoi(element_row[8].c_str());
	mario_state = atoi(element_row[9].c_str());			//trang thai cua mario
	mario_direction = atoi(element_row[10].c_str());		//kiem tra mario con nho hay k
 
	for (int i = 1; i <= height; i++)
	{
		string temp = dataSplit[i];
		vector<string> temp_vector = split(temp, ' ');

		int obj_id = atoi(temp_vector[0].c_str());
		int obj_state = atoi(temp_vector[1].c_str());
		float pos_x =  atoi(temp_vector[2].c_str());
		float pos_y =  atoi(temp_vector[3].c_str());
		int direction = atoi(temp_vector[6].c_str());
		int obj_type = atoi(temp_vector[7].c_str());


		//tao Object
		Object *obj;

		switch (obj_type)
		{
		case 21:	//gach binh thuong
			obj = new BrickEx(this->d3ddv, this->backBuffer, this->spriteHandler, pos_x, pos_y, obj_type, obj_state);
			obj->setIDObj(obj_id);
			//obj->setIDObjType(obj_type);
			break;

		case 22:	//nen dat
			obj = new CLand(this->d3ddv, this->backBuffer, this->spriteHandler, pos_x, pos_y, obj_type, obj_state);
			obj->setIDObj(obj_id);
			//obj->setIDObjType(obj_type);
			break;
		case 23:	//da
			obj = new Stone(this->d3ddv, this->backBuffer, this->spriteHandler, pos_x, pos_y, obj_type, obj_state);
			obj->setIDObj(obj_id);
			//obj->setIDObjType(obj_type);
			break;
		case 24:	//ong tron thap
			obj = new Pipe(this->d3ddv, this->backBuffer, this->spriteHandler, pos_x, pos_y, obj_type, obj_state);
			obj->setIDObj(obj_id);
			//obj->setIDObjType(obj_type);
			break;
		case 241:	//ong tron trung binh
			obj = new Pipe(this->d3ddv, this->backBuffer, this->spriteHandler, pos_x, pos_y, obj_type, obj_state);
			obj->setIDObj(obj_id);
			obj->setIDObjType(obj_type);
			break;
		case 242:	//ong tron cao
			obj = new Pipe(this->d3ddv, this->backBuffer, this->spriteHandler, pos_x, pos_y, obj_type, obj_state);
			obj->setIDObj(obj_id);
			obj->setIDObjType(obj_type);
			break;
		case 29:	//ong ngang
			obj = new Pipe(this->d3ddv, this->backBuffer, this->spriteHandler, pos_x, pos_y, obj_type, obj_state);
			obj->setIDObj(obj_id);
			//obj->setIDObjType(obj_type);
			break;
		case 25:	//gach dau hoi
			obj = new BrickQuestion(this->d3ddv, this->backBuffer, this->spriteHandler, pos_x, pos_y, obj_type, obj_state);
			obj->setIDObj(obj_id);
			//obj->setIDObjType(obj_type);
			break;
		case 26:	//gach an
			obj = new BrickQuestion(this->d3ddv, this->backBuffer, this->spriteHandler, pos_x, pos_y, obj_type, obj_state);
			obj->setIDObj(obj_id);
			//obj->setIDObjType(obj_type);
			break;
		case 27:	//gach chua 5 coin
			obj = new BrickEx(this->d3ddv, this->backBuffer, this->spriteHandler, pos_x, pos_y, obj_type, obj_state);
			obj->setIDObj(obj_id);
			//obj->setIDObjType(obj_type);
			break;
		case 28:	//gach chua sao
			obj = new BrickQuestion(this->d3ddv, this->backBuffer, this->spriteHandler, pos_x, pos_y, obj_type, obj_state);
			obj->setIDObj(obj_id);
			//obj->setIDObjType(obj_type);
			break;

		case 31:	//may
			obj = new CLoud(this->d3ddv, this->backBuffer, this->spriteHandler, pos_x, pos_y, obj_type, obj_state);
			obj->setIDObj(obj_id);
			//obj->setIDObjType(obj_type);
			break;
		case 32:	//co
			obj = new Grass(this->d3ddv, this->backBuffer, this->spriteHandler, pos_x, pos_y, obj_type, obj_state);
			obj->setIDObj(obj_id);
			//obj->setIDObjType(obj_type);
			break;
		case 33:	//mountain
			obj = new Mountain(this->d3ddv, this->backBuffer, this->spriteHandler, pos_x, pos_y, obj_type, obj_state);
			obj->setIDObj(obj_id);
			//obj->setIDObjType(obj_type);
			break;
		case 41:	//coin hien
			obj = new Coin(this->d3ddv, this->backBuffer, this->spriteHandler, pos_x, pos_y, obj_type, obj_state);
			obj->setIDObj(obj_id);
			//obj->setIDObjType(obj_type);
			break;
		case 46:	//coin an
			obj = new Coin(this->d3ddv, this->backBuffer, this->spriteHandler, pos_x, pos_y, obj_type, obj_state);
			obj->setIDObj(obj_id);
			//obj->setIDObjType(obj_type);
			break;
		case 47:	//5coin an
			obj = new Coin(this->d3ddv, this->backBuffer, this->spriteHandler, pos_x, pos_y, obj_type, IS_IDLE);
			obj->setIDObj(obj_id);
			obj->setIDObjType(obj_type);
			break;
		case 43:	//nam mang
			obj = new PowerUp(this->d3ddv, this->backBuffer, this->spriteHandler, pos_x, pos_y, obj_type, obj_state, direction);
			obj->setIDObj(obj_id);
			//obj->setIDObjType(obj_type);
			break;
		case 45:	//nam to, hoa
			obj = new PowerUp(this->d3ddv, this->backBuffer, this->spriteHandler, pos_x, pos_y, obj_type, obj_state, direction);
			obj->setIDObj(obj_id);
			//obj->setIDObjType(obj_type);
			break;

		case 42:	//cay an thit:pirhana
			obj = new Pirhana(this->d3ddv, this->backBuffer, this->spriteHandler, pos_x, pos_y, obj_type, obj_state);
			obj->setIDObj(obj_id);
			//obj->setIDObjType(obj_type);
			break;
		
		case 44:	//sao ba dao
			obj = new Star(this->d3ddv, this->backBuffer, this->spriteHandler, pos_x, pos_y, obj_type, obj_state, direction);
			obj->setIDObj(obj_id);
			//obj->setIDObjType(obj_type);
			break;

		case 11:	//goomba
			obj = new Goomba(this->d3ddv, this->backBuffer, this->spriteHandler, pos_x, pos_y, obj_type, obj_state, direction);
			obj->setIDObj(obj_id);
			//obj->setIDObjType(obj_type);
			break;

		case 12:	//koopa
			obj = new Koopa(this->d3ddv, this->backBuffer, this->spriteHandler, pos_x, pos_y, obj_type, obj_state, direction);
			obj->setIDObj(obj_id);
			//obj->setIDObjType(obj_type);
			break;

		case 51:	//checkpoint			
			obj = new CheckPoint(this->d3ddv, this->backBuffer, this->spriteHandler, pos_x, pos_y, obj_type, obj_state);
			obj->setIDObj(obj_id);
			//obj->setIDObjType(obj_type);
			break;
		}
		
		
		//obj = new Object(pos_x, pos_y, obj_id, obj_type);










		//them vao obj list
		obj_list.push_back(obj);
	}

}
 
void LoadMap::loadFileToMap(char* file_name)
{
	string data;
	ifstream fileStream(file_name);
	if (fileStream.is_open())
	{
		while (!fileStream.eof())
		{
			data += fileStream.get();
		}
	}
	vector<string> dataSplit = split(data, '\n');

	for (int i = 0; i < dataSplit.size() - 1; i++)
	{
		string temp = dataSplit[i];
		vector<string> temp_vector = split(temp, ' ');

		int id_node = atoi(temp_vector[0].c_str());
		int pos_x =  atoi(temp_vector[1].c_str());
		int pos_y =  atoi(temp_vector[2].c_str());
		int pos_x2 =  atoi(temp_vector[3].c_str());
		int pos_y2 =  atoi(temp_vector[4].c_str());

		//tao qNode
		QNode *q_obj;
		q_obj = new QNode(pos_x, pos_y, pos_x2 - pos_x, 0, id_node);

		//Dua obj vao list obj cua qNode
		//vector<int> id_obj_vt;
		if (temp_vector.size() >= 5)
		{
			for (int j = 5; j < temp_vector.size(); j++)
			{
				//add cac id object vao node
				int obj_id = atoi(temp_vector[j].c_str());

				Object *obj_game;
				list<Object*>::iterator k;
				for (k = this->obj_list.begin(); k != this->obj_list.end(); k++)
				{
					obj_game = *k;
					if (obj_id == obj_game->getIDObj())
					{
						q_obj->addGameObject(obj_game);
					}

				}
			}
		}
		//for (int j = 0; j < temp_vector.size(); j++)
		//{
		//	if (j >= 5)
		//	{
		//		//add cac id object vao node
		//		int obj_id = atoi(temp_vector[j].c_str());

		//		Object *obj_game;
		//		list<Object*>::iterator k;
		//		for (k = this->obj_list.begin(); k != this->obj_list.end(); k++)
		//		{
		//			obj_game = *k;
		//			if (obj_id == obj_game->getIDObj())
		//			{
		//				q_obj->addGameObject(obj_game);
		//			}
		//		}
		//	}
		//}

		//them node vao quad tree map
		qTree_map[q_obj->getIDNode()] = q_obj;

	}

	int ii;
}

void LoadMap::deserialize(QuadTree *qTree)
{
	QNode *p_qnode = (QNode*) qTree_map[0];
	
	qTree->setRoot(p_qnode);
	//q_tree->setRoot(p_qnode);
	build(qTree->getRoot());
	
	int iii;
}
//void LoadMap::build(QNode *n)
//{
//	int id_node = n->getIDNode();
//	
//	if (qTree_map[id_node * 10 + 1])
//	{
//		n->setLeftTop(qTree_map[id_node * 10 + 1]);
//		build(n->getLeftTop());
//	}
//	if (qTree_map[id_node * 10 + 2])
//	{
//		n->setRightTop(qTree_map[id_node * 10 + 2]);
//		build(n->getRightTop());
//	}
//	if (qTree_map[id_node * 10 + 3])
//	{
//		n->setLeftBottom(qTree_map[id_node * 10 + 3]);
//		build(n->getLeftBottom());
//	}
//	if (qTree_map[id_node * 10 + 4])
//	{
//		n->setRightBottom(qTree_map[id_node * 10 + 4]);
//		build(n->getRightBottom());
//	}
//}

void LoadMap::build(QNode *n)
{
	int id_node = n->getIDNode();

	if (!qTree_map[id_node * 10 + 1])
	{
		return;
	}


	if (qTree_map[id_node * 10 + 1])
	{
		n->setLeftTop(qTree_map[id_node * 10 + 1]);
	}
	
	if (qTree_map[id_node * 10 + 2])
	{
		n->setRightTop(qTree_map[id_node * 10 + 2]);
		
	}
	
	if (qTree_map[id_node * 10 + 3])
	{
		n->setLeftBottom(qTree_map[id_node * 10 + 3]);
		
	}
	
	if (qTree_map[id_node * 10 + 4])
	{
		n->setRightBottom(qTree_map[id_node * 10 + 4]);
		
	}
	
	 
	build(n->getLeftTop());
	build(n->getRightTop());
	build(n->getLeftBottom());
	build(n->getRightBottom());
}

void LoadMap::saveFileObj(char* file_name, list<Object*> obj_list_QT)
{
	//lay obj_list tu quadtree
	//sau do so sanh moi obj trong quadtree voi obj tuong ung trong obj_list cua map
	//cap nhat lai vi tri, trang thai cua obj
	Object *obj_game;
	list<Object*>::iterator i;

	Object *obj_game_QT;
	list<Object*>::iterator j;

	for (i = this->obj_list.begin(); i != this->obj_list.end(); i++)
	{
		obj_game = *i;
		for (j = obj_list_QT.begin(); j != obj_list_QT.end(); j++)
		{
			obj_game_QT = *j;
			if (obj_game->getIDObj() == obj_game_QT->getIDObj())
			{
				//cap nhat vi tri, trang thai obj
				//neu la goomba, koopa, nam mang, nam lon
				if (obj_game->getIDObjType() == 11 || obj_game->getIDObjType() == 12 || obj_game->getIDObjType() == 44 ||
					((obj_game->getIDObjType() == 43 || obj_game->getIDObjType() == 45) && obj_game->getObjState() == IS_MOVING))
				{
					obj_game->setPosX((int)obj_game_QT->getPosX());
					obj_game->setPosY((int)(obj_game_QT->getPosY() + 1));
				}
				else
				{
					obj_game->setPosX(obj_game_QT->getPosX());
					obj_game->setPosY(obj_game_QT->getPosY());					
				}
				obj_game->setObjState(obj_game_QT->getObjState());
			}
		}
	}

	//Ghi thong tin cac obj xuong file
	ofstream fileStream(file_name);
	Object* obj;
	list<Object*>::iterator iList;

	//ghi dong dau tien, so luong obj, so cot thong tin obj, so diem, so mang, so coin an dc, vi tri dau tien, vi tri tiep theo mario, trang thai mario, huong di chuyen
	int width = 8;
	int height = this->obj_list.size();
	fileStream<<width<<" "<<height<<" "<<numScore<<" "<<numLife<<" "<<numCoin<<" "<<posX_first<<" "<<posY_first<<" "<<posX_last<<" "<<posY_last<<" "<<mario_state<<" "<<mario_direction<<"\n";

	for (iList = this->obj_list.begin(); iList != this->obj_list.end(); iList++)
	{
		obj = *iList;
		//id obj, state obj, posx, posy, 0, 0 , huong cua obj, id type obj
		fileStream<<obj->getIDObj()<<" "<<obj->getObjState()<<" "<<obj->getPosX()<<" "<<obj->getPosY()<<" "<<0<<" "<<0<<" "<<obj->getDirection()<<" "<<obj->getIDObjType()<<"\n";
			
	}

	fileStream.close();
}
